package com.yuanlang.services.fasthdsf.core;

import com.yuanlang.common.ResultMap;
import com.yuanlang.common.util.SysUtils;
import com.yuanlang.common.util.SystemMsgCode;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.UUID;

@Component(value = "fileManager")
public class FileManager implements FileManagerConfig {
    private static Logger log = LoggerFactory.getLogger(FileManager.class);

    static {
        ClassPathResource cpr = new ClassPathResource(CLIENT_CONFIG_FILE); // 获取默认的配置文件
        try {
            ClientGlobal.init(cpr.getClassLoader().getResource(CLIENT_CONFIG_FILE).getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private final long serialVersionUID = 1L;
    private TrackerClient trackerClient = new TrackerClient();
    private TrackerServer trackerServer;
    private StorageServer storageServer;
    private StorageClient storageClient;

    /**
     * 初始化连接
     */
    private void initConnectionn() throws IOException {
        trackerServer = trackerClient.getConnection();
        storageClient = new StorageClient(trackerServer, storageServer);
    }

    public String upload(byte[] file, String extName) {
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] = new NameValuePair("author", FILE_DEFAULT_AUTHOR);
        String[] uploadResults = null;
        try {
            initConnectionn();
            uploadResults = storageClient.upload_file(file, extName, meta_list);
        } catch (IOException e) {
            log.error("IO Exception when uploadind the file(byte[]): ", e);
        } catch (Exception e) {
            log.error("Non IO Exception when uploadind the file(byte[]): ", e);
        }
        if (uploadResults == null) {
            log.error("upload file fail, error code: " + storageClient.getErrorCode());
            return null;
        }
        String groupName = uploadResults[0];
        String remoteFileName = uploadResults[1];
        String fileAbsolutePath = groupName + String.valueOf(SEPARATOR) + remoteFileName;
        if (log.isDebugEnabled())
            log.debug("upload file successfully!!!   remoteFileName:" + fileAbsolutePath);
        return fileAbsolutePath;
    }

    public String upload(FastDFSFile file) {
        if (log.isDebugEnabled())
            log.debug("File Name: " + file.getName() + "		File Length: " + file.getContent().length);
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] = new NameValuePair("author", FILE_DEFAULT_AUTHOR);
        String[] uploadResults = null;
        try {
            initConnectionn();
            uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
        } catch (IOException e) {
            log.error("IO Exception when uploadind the file: " + file.getName(), e);
        } catch (Exception e) {
            log.error("Non IO Exception when uploadind the file: " + file.getName(), e);
        }
        if (uploadResults == null) {
            log.error("upload file fail, error code: " + storageClient.getErrorCode());
            return null;
        }

        String groupName = uploadResults[0];
        String remoteFileName = uploadResults[1];
        /*String fileAbsolutePath = PROTOCOL + trackerServer.getInetSocketAddress().getHostName() + PORT_SEPARATOR
				+ TRACKER_NGNIX_PORT + SEPARATOR + groupName + SEPARATOR + remoteFileName;*/
        String fileAbsolutePath = groupName + String.valueOf(SEPARATOR) + remoteFileName;
        if (log.isDebugEnabled())
            log.debug("upload file successfully!!!   remoteFileName:" + fileAbsolutePath);
        return fileAbsolutePath;
    }

    public String upload(String localFileName) {
        if (log.isDebugEnabled())
            log.debug("File Name: " + localFileName);
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] = new NameValuePair("author", FILE_DEFAULT_AUTHOR);
        String[] uploadResults = null;
        try {
            initConnectionn();
            int index = localFileName.lastIndexOf(".");
            String extName = "";
            if (index >= 0) extName = localFileName.substring(index + 1);
            uploadResults = storageClient.upload_file(localFileName, extName, meta_list);
        } catch (IOException e) {
            log.error("IO Exception when uploadind the file: " + localFileName, e);
        } catch (Exception e) {
            log.error("Non IO Exception when uploadind the file: " + localFileName, e);
        }
        if (uploadResults == null) {
            log.error("upload file fail, error code: " + storageClient.getErrorCode());
            return null;
        }
        String groupName = uploadResults[0];
        String remoteFileName = uploadResults[1];
		/*String fileAbsolutePath = PROTOCOL + trackerServer.getInetSocketAddress().getHostName() + PORT_SEPARATOR
				+ TRACKER_NGNIX_PORT + SEPARATOR + groupName + SEPARATOR + remoteFileName;*/
        String fileAbsolutePath = groupName + String.valueOf(SEPARATOR) + remoteFileName;
        if (log.isDebugEnabled())
            log.debug("upload file successfully!!!   remoteFileName:" + fileAbsolutePath);
        return fileAbsolutePath;
    }

    public FileInfo getFile(String groupName, String remoteFileName) {
        try {
            initConnectionn();
            return storageClient.get_file_info(groupName, remoteFileName);
        } catch (IOException e) {
            log.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            log.error("Non IO Exception: Get File from Fast DFS failed", e);
        }
        return null;
    }

    public ResultMap downloadAsBytes(String groupName, String remoteFileName) {
        ResultMap resultMap = new ResultMap();
        try {
            initConnectionn();
            byte[] result = storageClient.download_file(groupName, remoteFileName);
            resultMap.setCode(SystemMsgCode.DFS_DOWNLOAD_SUCCESS.getResultCode());
            resultMap.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_SUCCESS.getResultCode()));
            resultMap.setData(result);
            return resultMap;
            //return OperationResult.succeedResult(result);
        } catch (IOException e) {
            log.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            log.error("Non IO Exception: Get File from Fast DFS failed", e);
        }
        resultMap.setCode(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode());
        resultMap.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode()));

        return resultMap;
    }

    public ResultMap download(String groupName, String remoteFileName, String savePath) {
        ResultMap resultMap = new ResultMap();
        try {
            initConnectionn();
            String fName = SysUtils.nullString(remoteFileName);
            int index = fName.lastIndexOf(".");
            String extName = "";
            if (index >= 0 && index < fName.length() - 1) {
                extName = "." + fName.substring(index + 1);
            }
            fName = savePath + UUID.randomUUID().toString() + extName;
            int result = -1, i = 3;
            while (result != 0 && i-- > 0) {
                result = storageClient.download_file(groupName, remoteFileName, fName);
            }
            if (result == 0) {
                resultMap.setCode(SystemMsgCode.DFS_DOWNLOAD_SUCCESS.getResultCode());
                resultMap.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_SUCCESS.getResultCode()));
                resultMap.setData(fName);
                //return OperationResult.succeedResult(fName);
                return resultMap;
            } else {
                resultMap.setCode(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode());
                resultMap.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode()));
                return resultMap;
                //return OperationResult.failedResult();
            }
        } catch (IOException e) {
            log.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            log.error("Non IO Exception: Get File from Fast DFS failed", e);
        }
        resultMap.setCode(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode());
        resultMap.setMsg(SystemMsgCode.getSystemMsg(SystemMsgCode.DFS_DOWNLOAD_FAILED.getResultCode()));
        return resultMap;
    }

    public void deleteFile(String groupName, String remoteFileName) throws Exception {
        initConnectionn();
        storageClient.delete_file(groupName, remoteFileName);
    }

    public StorageServer[] getStoreStorages(String groupName) throws IOException {
        initConnectionn();
        return trackerClient.getStoreStorages(trackerServer, groupName);
    }

    public ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
        initConnectionn();
        return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
    }

}
